import * as echarts from 'echarts';
import { ElMessage } from 'element-plus';
import { ECharts } from 'echarts';
import { debounce } from '/@/utils/debounce-throttle';
import {amountFormat, convertUnit} from "/@/utils/util";
import {getDiffDay} from "/@/utils/date";
// 主题色
const color = ref<string>('#1295ff');
const backgroundColor = ref<string>('#eceff4');
// 图表实例,Vue3使用了proxy，Echarts无法从中获取内部变量，所以使用shallowRef
// let instance = shallowRef<ECharts>()

export interface Chart {
	// 标题
	title?: string;
	// 图表类型: line | pie | bar
	type: string;
	// 图表id
	id: string;
	// 图表配置
	options?: any;
	fetch?: Function;
	params?: any;
	data?: Array<any>;
	// 是否金额
	isAmount?: boolean;
}

/**
 * 构建图表XY轴数据
 * @param data      数据
 * @param unit      单位：hour | day
 * @param isAmount  是否金额
 */
export const buildChartXYDataForTimestamp = (data: Array<any> = [], isAmount: boolean = false) => {
	const xData: string[] = [];
	const yData: any[] = [];
	const items: any[] = [];
	if (data && data.length > 0) {
		data.forEach((item) => {
			// YYYY-MM-DD HH | YYYY-MM-DD
			let label = ''
			if (item.label.length > 10) {
				// 获取小时
				label = item.label.substring(11, 13)
			} else {
				// 获取月日
				label = item.label.substring(5, 10)
			}
			let amountText = '';
			if (isAmount) {
				amountText += amountFormat(item.value);
			}
			xData.push(label);
			yData.push(item.value);
			// console.log(item);
			items.push({
				origin: item.label,
				label: label,
				value: item.value,
				isAmount: isAmount,
				amountText: amountText,
			});
		});
	}
	return { items: items, xData: xData, yData: yData };
};

// 获取Y轴间隔参数
export const getYIntervalParam = (yData: number[]) => {
	// 通过最大值然后获取可被5整除的数并赋值给最大值以此来计算出min和max的间隔数
	let max, min, interval;
	min = 0;
	let maxData = yData.length > 0 ? Math.max(...yData) : 0;
	const averageNum = Math.ceil(maxData / 5);
	max = (averageNum > 0 ? averageNum : 1) * 5;
	interval = Math.round(max / 5);
	return {
		min,
		max,
		interval,
	};
};

// 获取折线图X轴间隔参数
export const getXIntervalParam = (items) => {
	// 一天内的间隔函数,显示5个时间(0点,6点,12点,18点，23点)
	const oneDayFunc = (index: number) => {
		return index === 0 || index === 6 || index === 12 || index === 18 || index === items.length - 1;
	};

	if (!(items && items.length > 0)) {
		return 0;
	}
	const startItem = items[0];
	const endItem = items[items.length - 1];
	const startTime = new Date(startItem.origin.length > 10 ? startItem.origin + ':00:00' : startItem.origin + ' 00:00:00')
	const endTime = new Date(endItem.origin.length > 10 ? endItem.origin + ':00:00' : endItem.origin + ' 00:00:00')
	// 获取时间相差天数
	const diffDay = items && items.length > 1 ? getDiffDay(startTime, endTime) : 0;
	// console.log('diffDay', diffDay)
	// 一天内，显示当天时间
	if (diffDay <= 1) {
		return oneDayFunc;
	}
	// 近4天 -> 显示全部时间
	else if (diffDay > 1 && diffDay <= 4) {
		const interval = 0;
		// console.log('x轴 interval', interval)
		return interval;
	}
	// else if (diffDay >= 10 ) {
	//     const interval = items.length - 5
	//     return interval
	// }
	// 其余时间，相差天数从5天起每增加三天增加1个间隔以此类推，如：
	// 相差5-7天 -> 间隔为1
	// 相差8-10天 -> 间隔为2
	// 相差11-13天 -> 间隔为3
	// 相差14-16天 -> 间隔为4
	else {
		let interval = 1;
		let boundDay = 5;
		// 退出标识
		let flag = true;
		// 循环次数
		let num = 0;
		while (flag) {
			// 每3次（即每3天）增加1个间隔
			if (num > 0 && num % 3 == 0) {
				interval++;
			}
			if (diffDay <= boundDay) {
				flag = false;
				break;
			} else {
				boundDay++;
			}
			num++;
		}
		// console.log('x轴 interval', interval)
		return interval;
	}
};

// 获取折线图 options
export const getLineChartOptions = (res, options) => {
	// console.log('getLineChartOptions', res)
	const yIntervalParam = getYIntervalParam(res.yData);
	const xIntervalParam = getXIntervalParam(res.items);
	const defaultOptions = {
		calculable: true,
		// 自定义的颜色
		color: [color.value],
		tooltip: {
			trigger: 'axis',
			axisPointer: {
				label: {
					backgroundColor: '#ffffff',
				},
			},
			formatter: (params) => {
				// console.log('params', params)
				// 提示格式化：日期时间 + 格式化的金额
				// return `${params[0].data.dateTime}<br/>${params[0].data.isAmount ? params[0].data.amountText : params[0].data.value}`;

				return `${params[0].data.origin}<br/>${params[0].data.isAmount ? params[0].data.amountText : params[0].data.value}`;
			},
			backgroundColor: '#39404d',
			textStyle: {
				color: '#ffffff',
				fontSize: '13px',
				fontWeight: 'bold',
			},
		},
		grid: {
			bottom: '12px',
			top: '20px',
			left: '0px',
			right: '20px',
			// grid 区域是否包含坐标轴的刻度标签
			// containLabel 为 true 的时候：
			// grid.left grid.right grid.top grid.bottom grid.width grid.height 决定的是包括了坐标轴标签在内的所有内容所形成的矩形的位置。
			// 这常用于『防止标签溢出』的场景，标签溢出指的是，标签长度动态变化时，可能会溢出容器或者覆盖其他组件。
			containLabel: true,
		},
		graphic: {
			type: 'text',
			left: 'center',
			top: 'middle',
			silent: true,
			invisible: true,
			style: {
				fill: '#39404d',
				font: '14px "bold" ',
				text: '',
			},
		},
		xAxis: [
			{
				type: 'category',
				data: res.xData,
				boundaryGap: true,
				offset: 11,
				axisTick: {
					// 是否显示坐标轴刻度
					show: false,
				},
				axisLine: {
					show: true,
					lineStyle: {
						// #e9e9eb
						color: backgroundColor.value,
						type: 'solid',
					},
				},
				axisLabel: {
					//设置X轴显示参数 ->
					interval: xIntervalParam,
					textStyle: {
						color: '#39404d',
						padding: [0, 0, 0, 8],
						fontSize: 12,
						fontWeight: '500',
					},
					formatter: (value) => {
						return value + '';
					},
				},
			},
		],
		yAxis: [
			{
				type: 'value',
				offset: 0,

				min: yIntervalParam.min,
				max: yIntervalParam.max,
				interval: yIntervalParam.interval,

				axisTick: {
					//不显示坐标轴刻度线
					show: false,
				},
				axisLine: {
					//是否显示坐标轴轴线。
					show: false,
				},
				axisLabel: {
					//是否显示刻度值
					show: true,
					formatter: (value) => {
						return convertUnit(value);
					},
				},
				splitLine: {
					show: true,
					lineStyle: {
						type: 'solid',
						color: backgroundColor.value,
					},
				},
			},
		],
		series: [
			{
				// name: ,
				type: 'line',
				symbol: 'none',
				data: res.items,
				//平滑
				smooth: true,
				areaStyle: {
					color: {
						type: 'linear',
						x: 0,
						y: 0,
						x2: 0,
						y2: 1,
						colorStops: [
							// 渐变颜色
							{
								offset: 0,
								color: 'rgba(176, 123, 209, 0.26)',
							},
							{
								offset: 1,
								color: 'rgba(255, 255, 255, 0.26)',
							},
						],
						global: false,
					},
				},
			},
		],
	};
	return { ...defaultOptions, ...options };
};

// 获取柱状图options
export const getBarGraphOptions = (res, options) => {
	// console.log('getBarGraphOptions', res)
	const yIntervalParam = getYIntervalParam(res.yData);
	const xIntervalParam = getXIntervalParam(res.items);
	const defaultOptions = {
		// 自定义的颜色
		color: [color.value],
		tooltip: {
			trigger: 'axis',
			axisPointer: {
				label: {
					backgroundColor: '#ffffff',
				},
			},
			backgroundColor: '#39404d',
			textStyle: {
				color: '#ffffff',
				fontSize: '13px',
				fontWeight: 'bold',
			},
		},
		grid: {
			bottom: '12px',
			top: '20px',
			left: '0px',
			right: '0px',
			containLabel: true,
		},
		xAxis: {
			type: 'category',
			data: res.xData,
			// boundaryGap: false,
			offset: 3,
			axisTick: {
				show: false, // 不显示坐标轴刻度线
			},
			axisLabel: {
				//坐标轴刻度标签的相关设置
				interval: xIntervalParam,
				textStyle: {
					color: '#39404d',
					padding: [8, 0, 0, 0],
					fontSize: 12,
					fontWeight: '500',
				},
				formatter: function (value) {
					return value + '';
				},
			},
			axisLine: {
				show: true,
				lineStyle: {
					color: color.value,
					width: 2,
					type: 'solid',
				},
			},
		},
		yAxis: {
			type: 'value',
			offset: 0,

			min: yIntervalParam.min,
			max: yIntervalParam.max,
			interval: yIntervalParam.interval,

			axisTick: {
				show: false, //不显示坐标轴刻度线
			},
			axisLine: {
				show: false, //隐藏y轴
			},
			axisLabel: {
				show: true, //隐藏刻度值
				formatter: (value) => {
					return value;
				},
			},
			splitLine: {
				lineStyle: {
					color: ['#F2F5FA'],
					width: 1,
				},
			},
		},
		series: [
			{
				type: 'bar',
				data: res.yData,
				barWidth: '26',
				itemStyle: {
					color: color.value,
					normal: {
						label: {
							show: true, //开启显示
							position: 'top', //在上方显示
							formatter: function (val) {
								return val.value;
							},
							textStyle: {
								//数值样式
								color: color.value,
								fontSize: 10,
							},
						},
						color: color.value,
						// color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
						//     {offset: 0, color: '#9ad3ff'},   // 起点颜色
						//     {offset: 1, color: color.value}     // 终点颜色
						// ])
					},
				},
			},
		],
	};
	return {
		...defaultOptions,
		...options,
	};
};

// 获取饼图options
export const getPieOptions = (res, options) => {
	const defaultOptions = {
		tooltip: {
			trigger: 'item',
			formatter: '{b} : {c} ({d}%)',
		},
		color: (res as []).map((item: any) => item.color),
		legend: {
			show: false,
		},
		series: [
			{
				name: '',
				type: 'pie',
				data: res,
				radius: ['100%', '75%'],
				center: ['50%', '50%'],
				itemStyle: {
					borderWidth: 2, //边框的宽度
					borderColor: '#fff', //边框的颜色
				},
				label: {
					show: false,
				},
				labelLine: {
					show: false,
				},
				emphasis: {
					label: {
						show: false,
						fontSize: 16,
						fontWeight: 'bold',
					},
					itemStyle: {
						shadowBlur: 0,
						shadowOffsetX: 0,
						shadowColor: 'rgba(0, 0, 0, 0.5)',
					},
				},
			},
		],
	};
	return {
		...defaultOptions,
		...options,
	};
};

export function useChart(state: Chart) {
	// 图表实例
	let instance: ECharts | null = null;

	/**
	 * 图表-初始化
	 */
	const init = async () => {
		// console.log('chartInit', state)
		instance = echarts.init(document.getElementById(state.id)) as ECharts;
		// 获取数据
		if (state.fetch) {
			try {
				// 调用state.pageList方法发起分页查询
				const { ok, msg, data } = await state.fetch({ ...state.params });
				if (ok) {
					state.data = buildChartXYDataForTimestamp(data, state.isAmount);
				} else {
					ElMessage.error(msg);
				}
			} catch (err: any) {
				// 捕获异常并显示错误提示
				ElMessage.error(err.msg || err.data.msg);
			} finally {
				// do something
			}
		}
		if (state.data && state.data.length > 0) {
			state.data = buildChartXYDataForTimestamp(state.data,state.isAmount);
		}
		// console.log('state.data', state.data)

		// 配置图表
		switch (state.type) {
			// 折线图
			case 'line':
				instance.setOption(getLineChartOptions(state.data, state.options));
				break;
			// 饼图
			case 'pie':
				instance.setOption(getPieOptions(state.data, state.options));
				break;
			// 柱状图
			case 'bar':
				instance.setOption(getBarGraphOptions(state.data, state.options));
				break;
		}
	};

	// 图表-调整尺寸
	const resize = () => {
		// console.log('chartResize', window.innerWidth)
		instance && instance.resize();
	};

	onMounted(async () => {
		await init();
		window.addEventListener('resize', debounce(resize, 300));
	});
	onUnmounted(() => {
		window.removeEventListener('resize', resize);
		instance && instance.dispose();
	});
}
